/** 
 * \file gdasum.cu
 * \author Kyle E. Niemeyer
 * \date 10/03/2011
 *
 * Based on "dasum.f" from BLAS.
 *
 */

////////////////////////////////////////////////////////////////////////

/** gdasum takes the sum of the absolute values. BLAS level one.
 *
 * \param[in] n       vector dimension
 * \param[in] dx      array, dimension n
 * \param[in] incx    increment between elements of dx
 * \return    dasum  sum of the absolute values
 */
__device__ __inline__ double gdasum ( int n, const double *dx, int incx )
{
  
  double dasum = 0.0;
  
  if ( ( n <= 0 ) || ( incx <= 0 ) ) return dasum;
  
  if ( incx == 1 ) {
    
    // increment equal to 1
    
    // clean-up loop
    
    uint m = n % 6;
    
    if ( m != 0 ) {
      for ( uint i = 0; i < m; ++i ) {
        dasum += fabs( dx[i] );
      }
      
      if ( n < 6 ) {
        return dasum;
      } 
    }
      
    for ( uint i = m; i < n; i += 6 ) {
      dasum += fabs( dx[i] )     + fabs( dx[i + 1] ) + fabs( dx[i + 2] )
             + fabs( dx[i + 3] ) + fabs( dx[i + 4] ) + fabs( dx[i + 5] );
    }
      
  } else {
    
    // increment not equal to 1
    
    int nincx = n * incx;
    for ( uint i = 0; i < nincx; i+=incx ) {
      dasum += fabs( dx[i] );
    }
    
  }
  
  return dasum;
}